/**
 * @(#)MergeFilter.java
 *
 * Copyright: Copyright (c) 2003 Carnegie Mellon University
 *
 * This program is the implementation of the original system in the Assignment 1 of "Architectures
 * of Software Systems" class. For the details of each classes, please refer to the provided javadoc
 * documents. You will also find some useful information such as implementation decisions, coding
 * standards, and naming conventions in the README file.
 *
 * History:
 *
 * Date          Author              Change
 * ----------    ----------------    ---------------------------------------------------------------
 * 07/15/2003    Jung Soo Kim        Initial version.
 */


import java.io.*;


/**
 * A merge filter has two input ports and one output port. It relays data available on any input
 * ports to the output port without modification. 
 * <p>
 * There is no information or assumption of the data load on input ports. For that reason, when data
 * are available on both input ports, a merge filter can choose any input port over the other 
 * without causing a fairness problem.
 *
 * @author Jung Soo Kim
 * @version 1.0
 */
public class MergeFilter extends Filter {

    /**
     * The first input port.
     **/
    protected BufferedReader pInput1;

    /**
     * The second input port.
     **/
    protected BufferedReader pInput2;

    /**
     * The output port.
     **/
    protected BufferedWriter pOutput;

    /**
     * Construct a merge filter with the given name. A merge filter requires two input ports and
     * an output port. Ports are expected to be wrapped into a buffered character stream. This
     * approach enables using various different kinds of I/O mechanisms as well as pipes.
     * For example, a file can be directly plugged into a filter.
     *
     * @param sName   the string representing this filter's name
     * @param pInput1 the first input port of this filter
     * @param pInput2 the second input port of this filter
     * @param pOutput the output port of this filter
     */
    public MergeFilter(String sName,
                       BufferedReader pInput1, BufferedReader pInput2, BufferedWriter pOutput) {
        // Execute parent's constructor first.
        super(sName);

        // Initialize input/output ports.
        this.pInput1 = pInput1;
        this.pInput2 = pInput2;
        this.pOutput = pOutput;
    }

    /**
     * Tells if data are available on input ports.
     *
     * @return <code>true</code> if and only if this filter can read data from one of input ports.
     * @throws IOException
     */
    protected boolean ready() throws IOException {
        return this.pInput1.ready() || this.pInput2.ready();
    }

    /**
     * Read available data from one of input ports and write new data to the output port.
     *
     * @throws IOException
     */
    protected void work() throws IOException {
        /* Actually there is no need to parse the input data here. (Just for the consistency) */

        // Select which input port to read.
        BufferedReader pInput = this.pInput1.ready() ? this.pInput1 : this.pInput2;

        // Read a student record from the selected input port.
        Student objStudent = new Student(pInput.readLine());

        // Write the student record to the output port.
        this.pOutput.write(objStudent.toString());
        this.pOutput.newLine();
        this.pOutput.flush();
    }
}
